package mastermind.gui.controls;

import java.util.Timer;
import java.util.TimerTask;

import mastermind.dataholder.Row;
import mastermind.gui.contents.FieldUI;
import mastermind.img.ImageLoader;
import mastermind.logic.Game;
import mastermind.logic.Game.GameState;
import mastermind.logic.Game.GameType;
import mastermind.logic.ThreadManager;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;

/**
 * Diese Klasse zeigt die L&ouml;sung an oder nimmt eine L&ouml;sung durch
 * Benutzereingabe an
 */
public class SolutionUI extends Composite
{
	private RowUI		_compRow;
	private ButtonUI	_butOK;
	private Composite	_compSolutionImg;

	private int			_solHeight;

	/**
	 * Erstellt ein neues SolutionUI Objekt
	 * 
	 * @param parent
	 *            Eltern-Objekt, auf das das SolutionUI Objekt plaziert wird
	 * @param style
	 *            Zus&auml;zliche Style Informationen
	 */
	public SolutionUI(Composite parent, int style)
	{
		super(parent, style);
		createContents();
	}

	/**
	 * Hier werden alle Elemente erstellt, die ben&ouml;tigt werden um das
	 * Element anzuzeigen<br>
	 * Diese Funktion wird nur einmal pro Objekt aufgerufen
	 */
	private void createContents()
	{
		this.setBackground(new Color(Display.getDefault(), new RGB(220, 150, 110)));
		this.setBackgroundMode(SWT.INHERIT_FORCE);

		_compSolutionImg = new Composite(this, SWT.NONE);

		_compRow = new RowUI(this, SWT.NONE);
		_compRow.setVisible(false);

		_butOK = new ButtonUI(this, SWT.NONE);
		if (Game.getGameState() != GameState.WAITFORSOLUTION)
		{
			_butOK.setVisible(false);
			_butOK.setText("OK");
		}

		// Events
		_compRow.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent e)
			{
				if (Game.getGameState() == GameState.WAITFORSOLUTION && !FieldUI.getColorPickerUI().isAutoFill())
					_compRow.setPin(FieldUI.getColorPickerUI().getSelectedColor(), (byte) e.detail);
				if (!_butOK.isEnabled())
				{
					Row r = _compRow.getRow();
					for (int i = 0; i < Game.getCntHoles(); i++)
					{
						if (r.getColor(i) == -1)
						{
							return;
						}
					}
					_butOK.setEnabled(true);
				}
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e)
			{}
		});

		_butOK.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e)
			{
				if (Game.getGameType() != GameType.PC)
					hide();
				_butOK.setVisible(false);
				Game.setSolution(_compRow.getRow());
			}
		});

		_compSolutionImg.addPaintListener(new PaintListener() {
			@Override
			public void paintControl(PaintEvent e)
			{
				int w1 = ImageLoader.getSolution().getBounds().width;
				int w2 = _compSolutionImg.getBounds().width - 6;

				e.gc.drawImage(ImageLoader.getSolution(),
						0,
						0,
						ImageLoader.getSolution().getBounds().width,
						ImageLoader.getSolution().getBounds().height,
						(getBounds().width - (w1 < w2 ? w1 : w2)) / 2,
						0,
						w1 < w2 ? w1 : w2,
						_compSolutionImg.getBounds().height);

				e.gc.setForeground(new Color(Display.getDefault(), new RGB(150, 75, 0)));
				e.gc.drawRectangle(0, 0, _compSolutionImg.getBounds().width - 1, _compSolutionImg.getBounds().height - 1);

				e.gc.setForeground(new Color(Display.getDefault(), new RGB(160, 90, 25)));
				e.gc.drawRectangle(1, 1, _compSolutionImg.getBounds().width - 3, _compSolutionImg.getBounds().height - 3);
			}
		});

		init();
	}

	/**
	 * Zeigt die L&ouml;sung an
	 * 
	 * @param r
	 *            Die anzuzeigende L&ouml;sung
	 */
	public void show(Row r)
	{
		if (r != null)
		{
			for (byte i = 0; i < Game.getCntHoles(); i++)
			{
				_compRow.setPin(r.getColor(i), i);
			}
		}

		_solHeight = getBounds().height;

		_compRow.setVisible(true);
		_butOK.setVisible(Game.getGameState() == GameState.WAITFORSOLUTION);

		if (Game.getGameType() != GameType.PC)
		{
			final Timer timer = new Timer();
			ThreadManager.addTimer(timer);
			timer.schedule(new TimerTask() {
				@Override
				public void run()
				{
					Display.getDefault().asyncExec(new Runnable() {
						public void run()
						{
							_solHeight--;
							_compSolutionImg.setBounds(0, getBounds().height - _solHeight, getBounds().width, _solHeight);
							if (_solHeight <= 0)
							{
								timer.cancel();
							}
						}
					});

				}
			}, 0, 1);
			ThreadManager.removeTimer(timer);
		}
	}

	/**
	 * Versteckt die L&ouml;sung
	 */
	public void hide()
	{
		_solHeight = 0;

		final Timer timer = new Timer();
		ThreadManager.addTimer(timer);
		timer.schedule(new TimerTask() {
			@Override
			public void run()
			{
				Display.getDefault().asyncExec(new Runnable() {
					public void run()
					{
						_solHeight++;
						if (_solHeight > getBounds().height)
						{
							_compRow.setVisible(false);
							_butOK.setVisible(false);
							_compSolutionImg.setBounds(0, 0, getBounds().width, getBounds().height);
							timer.cancel();
						}
						else
						{
							_compSolutionImg.setBounds(0, getBounds().height - _solHeight, getBounds().width, _solHeight);
						}
					}
				});

			}
		}, 0, 1);
		ThreadManager.removeTimer(timer);
	}

	/**
	 * Initialisiert Gr&ouml;&szlig;e und Inhalte der einzelnen Elementen
	 */
	public void init()
	{
		_compRow.setBounds(
				41,
				5,
				ImageLoader.getPin((byte) 0).getBounds().width * Game.getCntHoles() + (Game.getCntHoles() + 1) * 3,
				ImageLoader.getPin((byte) 0).getBounds().height + 2 * 3
				);
		_compRow.init();

		_butOK.setBounds(_compRow.getBounds().width + _compRow.getBounds().x + 4, 8, 34, 24);
		_butOK.setEnabled(false);

		this.setSize(
				_butOK.getBounds().x + _butOK.getBounds().width + 47 + (Game.getCntHoles() - 3) * 3,
				_compRow.getBounds().height + 8
				);

		_compSolutionImg.setBounds(
				0,
				0,
				_butOK.getBounds().x + _butOK.getBounds().width + 47 + (Game.getCntHoles() - 3) * 3,
				_compRow.getBounds().height + 8
				);

		if (Game.getGameState() == GameState.WAITFORSOLUTION)
		{
			_compSolutionImg.setBounds(0, getBounds().height, getBounds().width, 0);
		}

		_compRow.setVisible(Game.getGameState() == GameState.WAITFORSOLUTION);
		_butOK.setVisible(Game.getGameState() == GameState.WAITFORSOLUTION);

	}

	/**
	 * Setzt einen Pin an die n&auml;chste freie Stelle.<br/>
	 * Sollten alle Stellen belegt sein, wird die Farbe reihum &uuml;berschrieben
	 * @param color Zu setzende Farb Id
	 */
	public void setPin(byte color)
	{
		_compRow.setPin(color);
		if (!_butOK.isEnabled())
		{
			Row r = _compRow.getRow();
			for (int i = 0; i < Game.getCntHoles(); i++)
			{
				if (r.getColor(i) == -1)
				{
					return;
				}
			}
			_butOK.setEnabled(true);
		}
	}
}
